package cn.tpshion.redismq.handler;

import cn.dev33.satoken.stp.StpUtil;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@ServerEndpoint(path = "/ws", port = "9097")
@Component
public class WebSocketHandler {

    private static final Map<String, Session> SESSION_MAP = new ConcurrentHashMap<>();

    @BeforeHandshake
    public void handshake(Session session, HttpHeaders headers){
        session.setSubprotocols("stomp");
        String token = headers.getAsString("token");
        log.info("token:{}", token);
        String userId = (String) StpUtil.getLoginIdByToken(token);
        if (!StringUtils.hasText(userId)) {
            log.error("Authentication failed!");
            session.close();
        }

        session.setAttribute("userId", userId);
    }

    @OnOpen
    public void onOpen(Session session){
        String userId = session.getAttribute("userId");
        log.info("new connection userId:{}", userId);

        // 保存用户信息
        SESSION_MAP.put(userId, session);
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        String userId = session.getAttribute("userId");
        log.info("one connection closed userId:{}", userId);

        // 删除用户
        SESSION_MAP.remove(userId);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        String userId = session.getAttribute("userId");
        log.error("onError userId:{} error:{}", userId, throwable.getMessage(), throwable);
        // 删除用户
        SESSION_MAP.remove(userId);
    }

    @OnMessage
    public void onMessage(Session session, String message) {
        String userId = session.getAttribute("userId");
        log.info("onMessage userId:{} message:{}", userId, message);
        //session.sendText("Hello Netty!");
    }

    @OnBinary
    public void onBinary(Session session, byte[] bytes) {
        for (byte b : bytes) {
            System.out.println(b);
        }
        session.sendBinary(bytes);
    }

    @OnEvent
    public void onEvent(Session session, Object evt) {
        if (evt instanceof IdleStateEvent idleStateEvent) {
            switch (idleStateEvent.state()) {
                case READER_IDLE:
                    log.info("read idle");
                    break;
                case WRITER_IDLE:
                    log.info("write idle");
                    break;
                case ALL_IDLE:
                    log.info("all idle");
                    break;
                default:
                    break;
            }
        }
    }

    public void sendMessage(String userId, String message) {
        Session session = SESSION_MAP.get(userId);
        if (session != null) {
            session.sendText(message);
        }
    }

    public boolean hasUser(String userId) {
        return SESSION_MAP.containsKey(userId);
    }

    public Session getSession(String userId) {
        return SESSION_MAP.get(userId);
    }
}
